You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(feature-flags): Align rule and target management with API contracts - #1719
I hit a 400 while testing rule authoring with the flags app: the SDK sent feature_flag, while the API requires flag_slug. Rule creation, listing, and the convenience helper now accept flagSlug and send the correct field. Target lookup and filtered pagination handle both API contracts: memberships expose ruleId; legacy targets expose value and valueType.
Membership creation sends only rule_id and target_id. The helper retains the created rule and confirmed memberships after a later failure, and existing target aliases remain available.
Release prerequisite: deploy the target membership API contract tested at revision 7a0095af09e7. Enable feature-flags-targeting-rules and turn off feature-flags-legacy-target-contract for membership authoring; the legacy contract takes precedence while enabled. Before enabling authoring, verify v2-capable runtime SDKs and rule-based-flag-evaluation in each affected environment.
Not covered by CI
Verified the changed contract tests fail against the previous SDK and pass with this update.
Ran the built SDK directly against the local API at 7a0095af09e7, without request translation: rule CRUD and evaluation-order pagination, membership lookup and combined filters, ascending/descending cursor pagination, duplicate/conflicting targets, helper success, partial failure, recovery, and sibling preservation all passed.
Checked the flags app with SDK rule authoring: matching user exclusion before organization inclusion produces v1 true and v2 false; reversing the rules changes the live decision to true.
Restored the legacy compatibility flag and verified target lookup/listing expose value/valueType without ruleId. Membership-only creation returns 400 in this mode, and the helper reports its retained empty rule.
Removed all disposable fixtures and restored the local compatibility override.
Repeat the successful membership check against the deployed API before release.
Proof
The updated SDK sent this request directly to the local API:
POST /flag_rules
{"flag_slug":"sdk-rule-update-1791399585805","target_type":"user","value":false}
HTTP 201
{"object":"flag_rule","id":"flag_rule_01M4BVRT8FQ3N94ZPEVQX31SFZ","position":0,"value":false}
It then sent POST /flag_targets with {"rule_id":"flag_rule_01M4BVRT8FQ3N94ZPEVQX31SFZ","target_id":"user_01KM490ND31XPKGTYFAC9APFJ4"}. The API returned HTTP 201 with membership flag_target_01M4BVRTACYNBCS05B5N3W7Y6W, the same rule_id, and no value/value_type fields. Lookup and filtered listing returned the same membership.
A later missing organization returned 404: CreateRuleWithTargetsError retained rule flag_rule_01M4BVRZBSC0MCY1ASQTC6230Q and its one confirmed membership; the next target was not attempted. Adding that next target to the retained rule succeeded.
Response excerpts omit unchanged fields. These IDs belonged to disposable local fixtures that have been removed.
### Issue 1
src/feature-flags/feature-flags.ts:84-87
The current API rejects this `POST /flag_targets` payload: it does not yet accept `rule_id` and requires `flag_slug` and `target_type`. Direct calls to `createFlagTarget` therefore return a 400. `createRuleWithTargets` creates the rule first, then fails on its first membership and leaves an empty rule to reconcile. This needs the AUTH-7084 API deployment and a successful end-to-end check before release.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Summary
The PR aligns rule requests with flag_slug, adds target lookup and filtered listing for membership and legacy contracts, and documents partial-failure recovery for the rule-and-targets helper.
Rule creation and listing use flagSlug; membership creation sends only the rule and target IDs.
Target reads expose the contract-specific fields, and list filters persist across pagination.
Membership authoring still depends on the specified API deployment and compatibility-flag configuration.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Create rule with flag_slug] --> B[Create memberships in order]
B --> C{Membership succeeds?}
C -->|Yes| D[Continue or return rule and targets]
C -->|No| E[Return error with rule and confirmed targets]
stanleyphu
changed the title
feat(feature-flags): Add rule-first management methods
feat(feature-flags): Align rule and target management with API contracts
Oct 7, 2026
Updated at 79c70669721269c3d45fdd909c54105bcfbbb02b to match the target contracts from workos/workos#75124. Direct live SDK checks against API revision 7a0095af09e7 now pass for membership creation, lookup/listing under both contracts, partial failure and recovery. The PR description retains the deployed-API prerequisite and compatibility gate requirements.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
I hit a 400 while testing rule authoring with the flags app: the SDK sent
feature_flag, while the API requiresflag_slug. Rule creation, listing, and the convenience helper now acceptflagSlugand send the correct field. Target lookup and filtered pagination handle both API contracts: memberships exposeruleId; legacy targets exposevalueandvalueType.Membership creation sends only
rule_idandtarget_id. The helper retains the created rule and confirmed memberships after a later failure, and existing target aliases remain available.Release prerequisite: deploy the target membership API contract tested at revision
7a0095af09e7. Enablefeature-flags-targeting-rulesand turn offfeature-flags-legacy-target-contractfor membership authoring; the legacy contract takes precedence while enabled. Before enabling authoring, verify v2-capable runtime SDKs andrule-based-flag-evaluationin each affected environment.Not covered by CI
7a0095af09e7, without request translation: rule CRUD and evaluation-order pagination, membership lookup and combined filters, ascending/descending cursor pagination, duplicate/conflicting targets, helper success, partial failure, recovery, and sibling preservation all passed.trueand v2false; reversing the rules changes the live decision totrue.value/valueTypewithoutruleId. Membership-only creation returns 400 in this mode, and the helper reports its retained empty rule.Repeat the successful membership check against the deployed API before release.
Proof
The updated SDK sent this request directly to the local API:
It then sent
POST /flag_targetswith{"rule_id":"flag_rule_01M4BVRT8FQ3N94ZPEVQX31SFZ","target_id":"user_01KM490ND31XPKGTYFAC9APFJ4"}. The API returned HTTP 201 with membershipflag_target_01M4BVRTACYNBCS05B5N3W7Y6W, the samerule_id, and novalue/value_typefields. Lookup and filtered listing returned the same membership.A later missing organization returned 404:
CreateRuleWithTargetsErrorretained ruleflag_rule_01M4BVRZBSC0MCY1ASQTC6230Qand its one confirmed membership; the next target was not attempted. Adding that next target to the retained rule succeeded.Response excerpts omit unchanged fields. These IDs belonged to disposable local fixtures that have been removed.
Fixes AUTH-7099